/**
 * App Bridge SDK
 * 
 * This SDK facilitates communication between H5 web applications and Android native app features.
 * It provides methods for voice input and voice assistant functionality.
 */

interface AppBridgeOptions {
  debug?: boolean;
  timeout?: number;
}

interface CallbackOptions {
  success?: (data: any) => void;
  fail?: (error: any) => void;
  complete?: () => void;
}

export class AppBridge {
  private static instance: AppBridge;
  private debug: boolean;
  private timeout: number;
  private isAndroid: boolean;
  private isIOS: boolean;
  private androidInterface: any;

  /**
   * Create a new AppBridge instance
   */
  private constructor(options: AppBridgeOptions = {}) {
    this.debug = options.debug || false;
    this.timeout = options.timeout || 5000;
    this.isAndroid = this.checkIsAndroid();
    this.isIOS = this.checkIsIOS();
    this.androidInterface = this.getAndroidInterface();
    
    this.log('AppBridge initialized');
    this.log(`Environment: ${this.getEnvironment()}`);
  }

  /**
   * Get the AppBridge singleton instance
   */
  public static getInstance(options?: AppBridgeOptions): AppBridge {
    if (!AppBridge.instance) {
      AppBridge.instance = new AppBridge(options);
    }
    return AppBridge.instance;
  }

  /**
   * Check if the current environment is Android
   */
  private checkIsAndroid(): boolean {
    return typeof window !== 'undefined' && 
           /android/i.test(navigator.userAgent);
  }

  /**
   * Check if the current environment is iOS
   */
  private checkIsIOS(): boolean {
    return typeof window !== 'undefined' && 
           /iphone|ipad|ipod/i.test(navigator.userAgent);
  }

  /**
   * Get the Android JavaScript interface
   */
  private getAndroidInterface(): any {
    if (this.isAndroid && typeof window !== 'undefined') {
      // The name 'XiaoAnJSBridge' should match the interface name defined in Android WebView
      return (window as any).XiaoAnJSBridge;
    }
    return null;
  }

  /**
   * Get the current environment description
   */
  public getEnvironment(): string {
    if (this.isAndroid) return 'Android';
    if (this.isIOS) return 'iOS';
    return 'Web';
  }

  /**
   * Check if the SDK is running in a native app environment
   */
  public isInApp(): boolean {
    return this.isAndroid || this.isIOS;
  }

  /**
   * Log messages when debug mode is enabled
   */
  private log(...args: any[]): void {
    if (this.debug) {
      console.log('[AppBridge]', ...args);
    }
  }

  /**
   * Call a native method with error handling and timeout
   */
  private callNativeMethod(
    methodName: string, 
    params: any = {}, 
    options: CallbackOptions = {}
  ): Promise<any> {
    return new Promise((resolve, reject) => {
      const { success, fail, complete } = options;
      
      // Set timeout for native method call
      const timeoutId = setTimeout(() => {
        const error = new Error(`Call to ${methodName} timed out after ${this.timeout}ms`);
        this.log('Timeout:', error);
        if (fail) fail(error);
        if (complete) complete();
        reject(error);
      }, this.timeout);
      
      try {
        if (this.isAndroid && this.androidInterface) {
          // For Android, we call the method on the JavaScript interface
          if (typeof this.androidInterface[methodName] === 'function') {
            const paramsJson = JSON.stringify(params);
            const callback = (resultJson: string) => {
              clearTimeout(timeoutId);
              try {
                const result = JSON.parse(resultJson);
                this.log(`${methodName} result:`, result);
                if (result.success) {
                  if (success) success(result.data);
                  if (complete) complete();
                  resolve(result.data);
                } else {
                  const error = new Error(result.message || 'Unknown error');
                  if (fail) fail(error);
                  if (complete) complete();
                  reject(error);
                }
              } catch (e) {
                const error = new Error('Failed to parse result: ' + e.message);
                if (fail) fail(error);
                if (complete) complete();
                reject(error);
              }
            };
            
            this.log(`Calling Android method: ${methodName}`, params);
            this.androidInterface[methodName](paramsJson, callback);
          } else {
            throw new Error(`Method ${methodName} not available in Android interface`);
          }
        } else if (this.isIOS) {
          // iOS implementation would go here
          // Using webkit message handlers or URL scheme
          throw new Error('iOS implementation not available yet');
        } else {
          throw new Error('Not in a native app environment');
        }
      } catch (error) {
        clearTimeout(timeoutId);
        this.log('Error:', error);
        if (fail) fail(error);
        if (complete) complete();
        reject(error);
      }
    });
  }

  /**
   * Start voice-to-text input
   * 
   * @param options Configuration options for voice input
   * @returns Promise that resolves with the recognized text
   */
  public startVoiceInput(options: {
    maxDuration?: number;  // Maximum recording duration in seconds
    language?: string;     // Language code (e.g., 'zh-CN', 'en-US')
    prompt?: string;       // Prompt text to show in the voice input UI
  } = {}): Promise<string> {
    return this.callNativeMethod('startVoiceInput', options)
      .then((result: any) => {
        return result.text || '';
      });
  }

  /**
   * Activate the voice assistant (小安)
   * 
   * @param options Configuration options for the voice assistant
   * @returns Promise that resolves when the assistant is activated
   */
  public activateVoiceAssistant(options: {
    query?: string;        // Initial query to process
    fullScreen?: boolean;  // Whether to show in full screen mode
    theme?: 'light' | 'dark'; // UI theme
  } = {}): Promise<void> {
    return this.callNativeMethod('activateVoiceAssistant', options);
  }
}

// Export a default instance
export default AppBridge.getInstance();
